package com.xmh.reptile.util;

import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.javascript.DefaultJavaScriptErrorListener;
import com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine;
import com.gargoylesoftware.htmlunit.javascript.host.Window;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

public class WebClientUtil {

    final static WebClient webClient = new WebClient(BrowserVersion.CHROME);// 新建一个模拟谷歌Chrome浏览器的浏览器客户端对象

    static {
        System.out.println("init .... ");
        webClient.getOptions().setThrowExceptionOnScriptError(false);// 当JS执行出错的时候是否抛出异常, 这里选择不需要
        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);// 当HTTP的状态非200时是否抛出异常, 这里选择不需要
        webClient.getOptions().setCssEnabled(false);// 是否启用CSS, 因为不需要展现页面, 所以不需要启用
        webClient.getOptions().setJavaScriptEnabled(false); // 很重要，启用JS
        webClient.setJavaScriptEngine(new MyJavaScriptEngine(webClient));// 自定义JavaScript引擎，有js错误不打印
        webClient.setAjaxController(new NicelyResynchronizingAjaxController());// 很重要，设置支持AJAX

//        webClient.getOptions().setTimeout(5000);
        webClient.setJavaScriptErrorListener(new MyJSErrorListener());
//        webClient.setJavaScriptTimeout(5000);
    }

    public static String getHtml(String url) throws IOException {
        HtmlPage page = webClient.getPage(url.trim());

        page.remove();

        webClient.waitForBackgroundJavaScript(1000);// 异步JS执行需要耗时,所以这里线程要阻塞30秒,等待异步JS执行结束

        return page.asXml();
//        return Jsoup.parse(html).select(cssQuery).text();
    }


    public static class MyJSErrorListener extends DefaultJavaScriptErrorListener {
        @Override
        public void scriptException(HtmlPage page, ScriptException scriptException) {
        }

        @Override
        public void timeoutError(HtmlPage page, long allowedTime, long executionTime) {
        }

        @Override
        public void malformedScriptURL(HtmlPage page, String url, MalformedURLException malformedURLException) {

        }

        @Override
        public void loadScriptError(HtmlPage page, URL scriptUrl, Exception exception) {

        }

        @Override
        public void warn(String message, String sourceName, int line, String lineSource, int lineOffset) {

        }
    }

    public static class MyJavaScriptEngine extends JavaScriptEngine {

        public MyJavaScriptEngine(WebClient webClient) {
            super(webClient);
        }

        @Override
        protected void handleJavaScriptException(final ScriptException scriptException, final boolean triggerOnError) {
            // Trigger window.onerror, if it has been set.
            HtmlPage page = scriptException.getPage();
            if (triggerOnError && page != null) {
                final WebWindow window = page.getEnclosingWindow();
                if (window != null) {
                    final Window w = (Window) window.getScriptableObject();
                    if (w != null) {
                        try {
                            w.triggerOnError(scriptException);
                        } catch (final Exception e) {
                            handleJavaScriptException(new ScriptException(page, e, null), false);
                        }
                    }
                }
            }
/*            final JavaScriptErrorListener javaScriptErrorListener = getWebClient().getJavaScriptErrorListener();
            if (javaScriptErrorListener != null) {
                javaScriptErrorListener.scriptException(page, scriptException);
            }
            // Throw a Java exception if the user wants us to.
            if (getWebClient().getOptions().isThrowExceptionOnScriptError()) {
                throw scriptException;
            }
            // Log the error; ScriptException instances provide good debug info.
            // LOG.info("Caught script exception", scriptException);*/
        }

    }
}
